package day04

import java.net.InetAddress

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

object SerializeTest_1 {

  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setAppName("SerializeTest1").setMaster("local[2]")
    val sc = new SparkContext(conf)
    val lines: RDD[String] = sc.parallelize(Array("xiaoli","xiaofang","xiaotian"))
    //---------------------
    //下面这个对象是在Driver端口创建的，因此该类必须继承Serializable类
    //!!!!!!!!class Rules extends Serializable!!!!!!!
    //val rules = new Rules
    //--------------
    //最好的方式是下面这个第三种，直接用单例对象
    val rules = ObjectRules
    //map方法中的函数里面的都是在Executor端执行的。
    val res: Array[(String, String, Int, String)] = lines.map(x => {
      //一条数据创建一次对象，效率极其低下，所以不建议在算子内部创建对象
      //val rules = new Rules  该对象是在Executor端创建的，在这里那么会创建3次，每次的对象地址都不同。
      //获取task的hostname,也就是判断该task所在节点名称。
      val hostname: String = InetAddress.getLocalHost.getHostName
      //获取当前线程名称
      val threadName: String = Thread.currentThread().getName
      //rules是在Executor中使用的
      (hostname, threadName, rules.rulesMap.getOrElse(x, 0), rules.toString)
    }).collect()
      //第四种方式：不需要再Driver端去创建对象，Rules也不需要序列化，直接用object类
      //(hostname, threadName, ObjectRules.rulesMap.getOrElse(x, 0), ObjectRules.toString)
    res.foreach(println)
  }

}
